package org.unt.logic;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList;

public class XPathLogic {

	private static Logger logger = Logger.getLogger(XPathLogic.class);

	private InputSource inputSource = null;
	private XPath xPath = null;
	private String absolutePathXML = null;

	public static void main(String[] args) {
		// System.out.println(new
		// XPathLogic("E:/java/test/pomPSA_ROOT.xml").findCheckstyleVersion());
		System.out.println(new XPathLogic("E:/java/test/pomSAMPLE.xml").findCheckstyleVersion());
	}

	public XPathLogic(String absolutePathXML) {

		XPathFactory factory = XPathFactory.newInstance();

		xPath = factory.newXPath();
		this.absolutePathXML = absolutePathXML;
	}

	public String findCheckstyleVersion() {

		String element = "/project/build/plugins/plugin/dependencies/dependency/version";
		DTMNodeList nodeList = (DTMNodeList) findNodeSet(element);

		if (nodeList == null || nodeList.getLength() == 0) {
			logger.debug("Not found any element for " + element);
			return null;
		}

		for (int i = 0; i < nodeList.getLength(); i++) {

			Node plugin = nodeList.item(i).getParentNode().getParentNode().getParentNode();

			for (int j = 0; j < plugin.getChildNodes().getLength(); j++) {
				if ("artifactId".equals(plugin.getChildNodes().item(j).getNodeName())) {
					if ("maven-checkstyle-plugin".equals(plugin.getChildNodes().item(j).getTextContent())) {

						return nodeList.item(i).getTextContent();
					}
				}
			}
		}

		logger.debug("Not found any element for " + element);
		return null;
	}

	public Object findNodeSet(String xmlPathExpression) {

		logger.debug("Starting...");

		XPathExpression xPathExpression = null;

		try {

			xPath.setNamespaceContext(new NamespaceContext() {

				public String getNamespaceURI(String prefix) {
					return "http://maven.apache.org/POM/4.0.0";
				}

				public String getPrefix(String namespaceURI) {
					if (namespaceURI.equals("http://maven.apache.org/POM/4.0.0")) {
						return "x";
					}

					return null;
				}

				public Iterator getPrefixes(String namespaceURI) {
					ArrayList list = new ArrayList();

					if (namespaceURI.equals("http://maven.apache.org/POM/4.0.0")) {
						list.add("x");
					}

					return list.iterator();
				}
			});

			//NamespaceContextImplementation context = new NamespaceContextImplementation();
			//context.declarePrefix("x", "http://maven.apache.org/POM/4.0.0");
			//xPath.setNamespaceContext(context);
			xPathExpression = xPath.compile(xmlPathExpression);
			// context.addNamespace("t", "http://www.w3.org/2001/XMLSchema");

			// xPath.setNamespaceContext(context);
		} catch (XPathExpressionException e) {
			throw new RuntimeException("XPathExpressionException: Cannot compile xPath expression " + xmlPathExpression, e);
		}

		try {
			inputSource = new InputSource(new FileInputStream(absolutePathXML));
		} catch (FileNotFoundException e) {
			throw new RuntimeException("FileNotFoundException: Cannot find file from ");
		}

		try {
			return xPathExpression.evaluate(inputSource, XPathConstants.NODESET);
		} catch (XPathExpressionException e) {
			throw new RuntimeException("XPathExpressionException: Cannot evaluate xPath expression " + xmlPathExpression + " from InputSource "
					+ inputSource, e);
		}
	}

	public String findUniqueValue(String xmlPathExpression) {

		logger.info("Starting...");

		XPathExpression xPathExpression = null;

		try {
			xPathExpression = xPath.compile(xmlPathExpression);
		} catch (XPathExpressionException e) {
			throw new RuntimeException("XPathExpressionException : Cannot compile xPath expression " + xmlPathExpression, e);
		}

		try {
			inputSource = new InputSource(new FileInputStream(absolutePathXML));
		} catch (FileNotFoundException e) {
			throw new RuntimeException("FileNotFoundException : Cannot find file from ");
		}

		try {
			String output = xPathExpression.evaluate(inputSource);
			logger.info(output);
			return output;
		} catch (XPathExpressionException e) {
			throw new RuntimeException("XPathExpressionException : Cannot evaluate xPath expression " + xmlPathExpression + " from InputSource "
					+ inputSource, e);
		}
	}
}
